-- -------------------------------------------------------------------------
-- UI/state.lua
-- UI State Management
-- -------------------------------------------------------------------------

local state = {}

-- [Configuration Constants]
state.constants = {
    -- Screen defaults
    SCREEN_DEFAULT_WIDTH = 1920,
    SCREEN_DEFAULT_HEIGHT = 1080,
    SCREEN_MIN_SCALE = 0.5,

    -- Text width cache settings
    TEXT_WIDTH_CACHE_LIMIT = 3000,
    TEXT_WIDTH_CACHE_EVICT_COUNT = 900,
    TEXT_WIDTH_CACHE_EVICT_PERCENTAGE = 0.3,

    -- Resolution check interval (seconds)
    RES_CHECK_INTERVAL = 1.0,

    -- Animation durations (seconds) - now configurable via base.click_anim_duration
    CLICK_ANIMATION_DURATION = 0.25,

    -- Notification flash cooldown (seconds)
    NOTIFICATION_FLASH_COOLDOWN = 1.5,

    -- Scroll behavior - now configurable via base.scroll_speed
    SCROLL_SPEED = 60,
    MIN_SCROLLBAR_THUMB_SIZE = 20,
    MIN_COMBO_THUMB_SIZE = 20,
    MIN_SCROLLBAR_WIDTH = 6,
    MIN_SCROLLBAR_HIT_WIDTH = 16,

    -- Text rendering
    TEXT_MIN_FONT_SIZE = 8,
    TEXT_WIDTH_ESTIMATE_FACTOR = 0.55,
}

-- Helper function to get config value with fallback
function state.get_config_value(key, fallback)
    local config_sys = state.deps.config_sys
    if config_sys and config_sys.data and config_sys.data.current then
        local val = config_sys.data.current[key]
        if val ~= nil then return val end
    end
    return fallback
end

-- Control IDs to block when menu is open
state.BLOCK_CONTROLS = {
    1, 2, 34, 35, 24, 25, 44, 140, 141, 142, 257, 263, 264,
    68, 69, 70, 91, 92, 14, 15, 16, 17, 37, 261, 262, 99, 100, 115, 116,
    81, 82, 83, 84, 332, 333,
    241, 242,
    106 -- VEH_FLY_MOUSE_CONTROL_OVERRIDE (disable mouse steering in vehicles)
}

-- [UI State]
state.ui = {
    open = false,
    dragging = false,
    drag_offset = {x = 0, y = 0},
    cx = 0,
    cy = 0,
    width_override = nil,
    active_id = nil,
    active_combo = nil,
    text_input_active = false,
    post_draw_queue = {},
    click_animations = {},
    checkbox_animations = {},
    active_tab = 1,
    settings_tab_index = nil,
    block_input = true,
    block_input_toggle = true,
    scale_factor = 1.0,
    screen_res = {x = 1920, y = 1080},
    scroll_y = 0,
    scroll_target = 0,
    content_h = 0,
    visible_h = 0,
    scroll_consumed = false,
    scroll_states = {},
    combo_states = {},
    input_states = {},
    caps_lock = false,
    collapsible_states = {},
    char_buffer = {},
    char_event_id = nil,
    header_end_y = 0,
    clip_rect = {x = 0, y = 0, w = 0, h = 0},
    is_clipped = false,
    input = {
        mouse_pos = {x = 0, y = 0},
        mouse_left_pressed = false,
        mouse_left_just_pressed = false
    },
    layout_cache = {},
    layout_counter = 0,
    notifications = {},
    bg_texture = nil,
    bg_path_loaded = nil,
    sidebar_textures = {},
    delta_time = 0.016,
    window_y_start = 0,
    subtab_offset = 0,
    in_scroll_context = false,
    -- Menu Hints Overlay state
    menu_hint = {
        current = nil,      -- Current hint text
        last_update = 0     -- Last update time (for auto-timeout)
    },
    -- Widget ID context stack (for automatic unique ID generation)
    id_context_stack = {},
}

-- [Cache State]
state.cache = {
    text_width = {},
    text_width_size = 0,
    text_width_order = {},
    color_userdata = {},
    color_alpha = {},
    last_res_check = 0,
}

-- [Dependencies]
state.deps = {
    config_sys = nil,
    natives = nil,
    debugger = nil,
    lexis = nil,
}

-- [Native Functions Cache]
state.natives_cache = {
    DISABLE_CONTROL_ACTION = nil,
    DISABLE_PLAYER_FIRING = nil,
    IS_CONTROL_JUST_PRESSED = nil,
    PLAYER_ID = nil,
}

-- [State Access Methods]
function state.set_dependency(name, value)
    state.deps[name] = value
end

function state.get_dependency(name)
    return state.deps[name]
end

function state.reset_cache()
    state.cache.color_userdata = {}
    state.cache.color_alpha = {}
    state.cache.text_width = {}
    state.cache.text_width_order = {}
    state.cache.text_width_size = 0
    state.ui.sidebar_textures = {}

    state.ui.scroll_states = {}

    -- Protect active combo state to prevent mouse freeze when clear_cache() is called
    -- while a dropdown menu is open (e.g., when changing theme from within Settings)
    local active_combo_id = state.ui.active_combo
    local active_combo_state = nil
    if active_combo_id then
        active_combo_state = state.ui.combo_states[active_combo_id]
    end

    state.ui.combo_states = {}

    if active_combo_state and active_combo_id then
        state.ui.combo_states[active_combo_id] = active_combo_state
    end

    state.ui.input_states = {}
    state.ui.collapsible_states = {}
    state.ui.click_animations = {}
    state.ui.checkbox_animations = {}

    state.ui.layout_cache = {}
end

function state.reset_color_cache()
    state.cache.color_userdata = {}
    state.cache.color_alpha = {}
end

-- [Widget ID Context Stack Functions]
-- Used to automatically generate unique widget IDs based on current Group context

--- Push a context name onto the ID stack (called when entering a Group)
---@param name string Context name (typically Group label)
function state.push_id_context(name)
    local stack = state.ui.id_context_stack
    stack[#stack + 1] = name
end

--- Pop the last context from the ID stack (called when leaving a Group)
function state.pop_id_context()
    local stack = state.ui.id_context_stack
    if #stack > 0 then
        stack[#stack] = nil
    end
end

--- Get the full widget ID by combining context stack with label
--- This ensures widgets with same label in different Groups have unique IDs
---@param label string Widget label
---@return string Full unique ID
function state.get_widget_id(label)
    local stack = state.ui.id_context_stack
    if #stack == 0 then
        return label
    end
    -- Combine all context names with the label
    -- Example: "Door Control" + "Front Left" -> "Door Control/Front Left"
    local context = table.concat(stack, "/")
    return context .. "/" .. label
end

-- [Lua 5.4] <const> for cleanup thresholds
local STATE_CLEANUP_THRESHOLD <const> = 100
local STATE_CLEANUP_RATIO <const> = 0.5

-- [Lua 5.4] <const> for function references
local next <const> = next
local math_floor <const> = math.floor

function state.cleanup_dynamic_states()
    local ui = state.ui

    local function cleanup_table(tbl)
        if not next(tbl) then return end

        local count = 0
        local keys = {}
        for key in next, tbl do
            count = count + 1
            keys[count] = key
            if count > STATE_CLEANUP_THRESHOLD then break end
        end

        if count > STATE_CLEANUP_THRESHOLD then
            local to_remove = math_floor(count * STATE_CLEANUP_RATIO)
            for i = 1, to_remove do
                tbl[keys[i]] = nil
            end
        end
    end

    cleanup_table(ui.scroll_states)
    cleanup_table(ui.combo_states)
    cleanup_table(ui.input_states)
    cleanup_table(ui.collapsible_states)
    cleanup_table(ui.layout_cache)
end

return state
